#ifndef MESH_H
#define MESH_H

#include "Engine.h"
#include "Renderer.h"
#include "Vector3.h"
#include "Matrix.h"

namespace Cvekas {

/// Contains geometry information for 3d object
class Mesh : public boost::noncopyable
{
public:
	/// Constructor. Loads mesh from .cmf file
	Mesh(const std::string& path);

	/// Constructor. Makes mesh from provided buffers. Index buffer can be null
	Mesh(VertexBufferPtr vb, IndexBufferPtr ib);

	/// Destructor
	virtual ~Mesh() {};

	IndexBufferPtr getIndexBuffer() { return index_buffer; };
	VertexBufferPtr getVertexBuffer() { return vertex_buffer; };

protected:
	IndexBufferPtr index_buffer;
	VertexBufferPtr vertex_buffer;

private:
	void cmf1_load(std::ifstream& input, const std::string& name, uint vertex_offset, uint index_offset);
};

typedef boost::shared_ptr<Mesh> MeshPtr;

/// Allows to easily send Mesh to Renderer
class RenderableMesh : public Renderable, public boost::noncopyable
{
public:
	/// Constructor. effect_params can be null, in that case only auto params will be applied.
	RenderableMesh(MeshPtr mesh, EffectPtr effect, EffectParamsPtr effect_params, 
		uint priority, uint passes = 1);

	/// Destructor
	virtual ~RenderableMesh();

	virtual void onPreRender(uint16 batch_id);
	virtual uint getBatches(Batch** batches);

	Vector3 getPosition() { return position; };
	Vector3 getRotation() { return rotation; };
	Vector3 getScale() { return scale; };

	void setPosition(const Vector3& position) { this->position = position; };
	void setRotation(const Vector3& rotation) { this->rotation = rotation; };
	void setScale(const Vector3& scale) { this->scale = scale; };

protected:
	uint passes;
	uint priority;
	Batch* batches;

	MeshPtr mesh;
	EffectPtr effect;
	EffectParamsPtr effect_params;

	Vector3 position;
	Vector3 rotation;
	Vector3 scale;
	Matrix world;
};

typedef boost::shared_ptr<RenderableMesh> RenderableMeshPtr;

} // namespace

#endif